package com.nineclock.system.service.impl;

import com.google.common.collect.Lists;

import java.util.Arrays;
import java.util.Date;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nineclock.common.constant.NcConstant;
import com.nineclock.common.constant.SMSConstant;
import com.nineclock.common.enums.MessageTypeEnum;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.oss.OssClientUtils;
import com.nineclock.common.threadlocal.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.system.dto.*;
import com.nineclock.system.im.HxImManager;
import com.nineclock.system.mapper.*;
import com.nineclock.system.msg.MessageDTO;
import com.nineclock.system.pojo.*;
import com.nineclock.system.service.SysCompanyService;
import com.nineclock.system.service.SysUserService;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Map;

@Service
@Transactional
public class SysCompanyServiceImpl implements SysCompanyService {
    @Autowired
    private SysCompanyMapper sysCompanyMapper;
    @Autowired
    private OssClientUtils ossClientUtils;
    @Autowired
    private SysCompanyUserMapper sysCompanyUserMapper;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private SysCompanyUserRoleMapper sysCompanyUserRoleMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private HxImManager manager;

    @Override
    public List<SysCompanyDTO> queryUserJoinCompany(Long userId) {
        if (userId == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        List<SysCompany> sysCompanys = sysCompanyMapper.queryUserJoinCompany(userId);
        if (CollectionUtils.isEmpty(sysCompanys)) {
            throw new NcException(ResponseEnum.USER_NOT_JOIN_COMPANY);
        }
        return BeanHelper.copyWithCollection(sysCompanys, SysCompanyDTO.class);
    }

    @Override
    public SysCompanyDTO findCompany() {
        Long companyId = CurrentUserHolder.get().getCompanyId();
        SysCompany sysCompany = sysCompanyMapper.selectById(companyId);
        return BeanHelper.copyProperties(sysCompany, SysCompanyDTO.class);
    }

    @Override
    public String uploadOSS(MultipartFile file) throws Exception {
        if (file == null) {
            throw new NcException(ResponseEnum.FILE_UPLOAD_ERROR);
        }
        String contentType = file.getContentType();
        if (!NcConstant.ALLOWED_IMG_TYPES.contains(contentType)) {
            throw new NcException(ResponseEnum.INVALID_FILE_TYPE);
        }

        if (file.getSize() > NcConstant.maxFileSize) {
            throw new NcException(ResponseEnum.FILE_SIZE_EXCEED_MAX_LIMIT);
        }
        String url = ossClientUtils.uploadFile(file.getOriginalFilename(), file.getInputStream());
        return url;
    }

    @Override
    public void updateCompany(SysCompanyDTO sysCompanyDTO) {
        Long companyId = CurrentUserHolder.get().getCompanyId();
        SysCompany sysCompany = new SysCompany();
        sysCompany.setName(sysCompanyDTO.getName());
        sysCompany.setLogo(sysCompanyDTO.getLogo());
        sysCompany.setId(companyId);
        sysCompanyMapper.updateById(sysCompany);

        SysCompanyUser sysCompanyUser = new SysCompanyUser();

        sysCompanyUser.setCompanyName(sysCompanyDTO.getName());
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, companyId);
        sysCompanyUserMapper.update(sysCompanyUser, wrapper);
    }

    @Override
    public SysCompanyUserDTO getCurrentAdmin() {
        Long companyId = CurrentUserHolder.get().getCompanyId();
        SysCompanyUser sysCompanyUser = sysCompanyUserMapper.getCurrentAdminByCompanyId(companyId);
        return BeanHelper.copyProperties(sysCompanyUser, SysCompanyUserDTO.class);
    }

    @Override
    public List<SysCompanyDTO> listCompany(String keyword) {
        if (StringUtils.isEmpty(keyword)) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        LambdaQueryWrapper<SysCompany> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(SysCompany::getName, keyword);
        List<SysCompany> sysCompanyList = sysCompanyMapper.selectList(wrapper);
        return BeanHelper.copyWithCollection(sysCompanyList, SysCompanyDTO.class);
    }

    @Override
    public void applyJoinCompany(SysApplyJoinCompanyUserDTO sysApplyJoinCompanyUserDTO) {
        if (sysApplyJoinCompanyUserDTO == null || sysApplyJoinCompanyUserDTO.getMobile() == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        SysUserDTO sysUserDTO = sysUserService.queryUser(sysApplyJoinCompanyUserDTO.getMobile());
        SysUser sysUser = BeanHelper.copyProperties(sysUserDTO, SysUser.class);
        sysUser.setUsername(sysApplyJoinCompanyUserDTO.getUserName());
        sysUser.setEmail(sysApplyJoinCompanyUserDTO.getEmail());
        sysUser.setUpdateTime(new Date());
        sysUser.setLastLoginCompanyId(sysApplyJoinCompanyUserDTO.getCompanyId());
        sysUserMapper.updateById(sysUser);
        //更新企业员工信息
        SysCompanyUser sysCompanyUser = new SysCompanyUser();
        sysCompanyUser.setUserId(sysUser.getId());
        sysCompanyUser.setCompanyId(sysApplyJoinCompanyUserDTO.getCompanyId());
        sysCompanyUser.setCompanyName(sysApplyJoinCompanyUserDTO.getCompanyName());
        sysCompanyUser.setPost(sysApplyJoinCompanyUserDTO.getPost());
        sysCompanyUser.setEmail(sysApplyJoinCompanyUserDTO.getEmail());
        sysCompanyUser.setTimeEntry(new Date());
        sysCompanyUser.setRemark(sysApplyJoinCompanyUserDTO.getApplyReason());
        sysCompanyUser.setEnable((short) 0);
        sysCompanyUser.setCreateTime(new Date());
        sysCompanyUser.setUpdateTime(new Date());
        sysCompanyUser.setMobile(sysApplyJoinCompanyUserDTO.getMobile());
        sysCompanyUser.setUserName(sysApplyJoinCompanyUserDTO.getUserName());
        sysCompanyUser.setImageUrl(sysApplyJoinCompanyUserDTO.getImageUrl());
        sysCompanyUserMapper.insert(sysCompanyUser);
        // 推送消息给管理员，发送消息至MQ，消息微服务接收消息
        // 定义消息内容
        MessageDTO messageDTO = new MessageDTO();
        messageDTO.setMessageType(MessageTypeEnum.COMPANY_APPLY.getType()); // 消息类型
        messageDTO.setCompanyId(sysCompanyUser.getCompanyId().toString()); // 公司id
        messageDTO.setTitle(MessageTypeEnum.COMPANY_APPLY.getTitle()); // 标题
        messageDTO.setContent(sysCompanyUser.getUserName() + " 申请加入企业，请及时审批"); // 内容
        messageDTO.setUseStatus(0); // 未读
        messageDTO.setAudience(MessageTypeEnum.COMPANY_APPLY.getAudience()); // 消息作用域

        // 获取当前企业主管理员
        SysCompanyUser mainAdmin = sysCompanyUserMapper.getCurrentAdminByCompanyId(sysCompanyUser.getCompanyId());
        messageDTO.setTargets(Arrays.asList(mainAdmin.getMobile())); // 目标用户，即审批人

        messageDTO.setApproveStatue(0); // 未审核
        messageDTO.setApplyUserId(sysCompanyUser.getUserId()); // 申请用户ID
        messageDTO.setApplyUsername(sysCompanyUser.getUserName()); // 申请用户名称

        messageDTO.setApproveUserId(mainAdmin.getUserId()); // 审批用户id
        messageDTO.setApproveUsername(mainAdmin.getUserName()); // 审批用户名称

        // 发送消息，参数1-消息的主题:标签，参数2-消息内容（一般用json字符串）
        rocketMQTemplate.convertAndSend("messagePushTopic", JSON.toJSONString(messageDTO));
    }

    @Override
    public void allowedJoinCompany(SysAllowedJoinCompanyUserDTO allowedJoinCompanyUserDTO) {
        SysCompanyUser sysCompanyUser = null;
        if (allowedJoinCompanyUserDTO.getApproved()) {
            LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
            wrapper.eq(SysCompanyUser::getUserId, allowedJoinCompanyUserDTO.getApplyUserId());
            sysCompanyUser = sysCompanyUserMapper.selectOne(wrapper);

            sysCompanyUser.setUpdateTime(new Date());
            sysCompanyUser.setEnable((short) 1);
            sysCompanyUser.setRemark(allowedJoinCompanyUserDTO.getRemark());
            sysCompanyUserMapper.updateById(sysCompanyUser);
            SysUser sysUser = new SysUser();
            sysUser.setUsername(sysCompanyUser.getMobile());
            //TODO 环信云注册用户默认密码123456
            sysUser.setPassword("123456");
            manager.registerUser2HuanXing(sysUser);
            //SysCompanyUser currentAdmin = sysCompanyUserMapper.getCurrentAdminByCompanyId(CurrentUserHolder.get().getCompanyId());

            MessageDTO messageDTO = new MessageDTO();
            messageDTO.setMessageType(MessageTypeEnum.COMPANY_APPLY_PASS.getType());
            messageDTO.setCompanyId(CurrentUserHolder.get().getCompanyId().toString());
            messageDTO.setTitle(MessageTypeEnum.COMPANY_APPLY_PASS.getTitle());
            messageDTO.setContent(sysCompanyUser.getUserName() + " 申请加入企业，已通过");
            messageDTO.setUseStatus(0);
            messageDTO.setAudience(MessageTypeEnum.COMPANY_APPLY_PASS.getAudience());
            messageDTO.setTargets(Arrays.asList(sysCompanyUser.getMobile()));
            messageDTO.setApproveStatue(1);
            messageDTO.setApplyUserId(sysCompanyUser.getUserId());
            messageDTO.setApplyUsername(sysCompanyUser.getUserName());
            messageDTO.setApproveUserId(CurrentUserHolder.get().getId());
            messageDTO.setApproveUsername(CurrentUserHolder.get().getUsername());
            rocketMQTemplate.convertAndSend("messagePushTopic", JSON.toJSONString(messageDTO));

            rocketMQTemplate.convertAndSend("allowedJoinCompanyTopic", allowedJoinCompanyUserDTO.getNotifyMsgId());



        } else {
            LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
            wrapper.eq(SysCompanyUser::getUserId, allowedJoinCompanyUserDTO.getApplyUserId());
            sysCompanyUser = sysCompanyUserMapper.selectOne(wrapper);
            MessageDTO messageDTO = new MessageDTO();
            messageDTO.setMessageType(MessageTypeEnum.COMPANY_APPLY_Fail.getType());
            messageDTO.setCompanyId(CurrentUserHolder.get().getCompanyId().toString());
            messageDTO.setTitle(MessageTypeEnum.COMPANY_APPLY_Fail.getTitle());
            messageDTO.setContent(sysCompanyUser.getUserName() + " 申请加入企业，未通过");
            messageDTO.setUseStatus(0);
            messageDTO.setAudience(MessageTypeEnum.COMPANY_APPLY_PASS.getAudience());
            messageDTO.setTargets(Arrays.asList(sysCompanyUser.getMobile()));
            messageDTO.setApproveStatue(1);
            messageDTO.setApplyUserId(sysCompanyUser.getUserId());
            messageDTO.setApplyUsername(sysCompanyUser.getUserName());
            messageDTO.setApproveUserId(CurrentUserHolder.get().getId());
            messageDTO.setApproveUsername(CurrentUserHolder.get().getUsername());
            rocketMQTemplate.convertAndSend("messagePushTopic", JSON.toJSONString(messageDTO));


            sysCompanyUserMapper.delete(wrapper);


            rocketMQTemplate.convertAndSend("refusedJoinCompanyTopic", allowedJoinCompanyUserDTO.getNotifyMsgId());
        }
    }

    @Override
    public void changeAdmin(Map<String, Object> map) {
        Long companyId = CurrentUserHolder.get().getCompanyId();
        String code = (String) map.get("code");
        Long companyuserId = Long.valueOf(map.get("userId").toString());
        if (StringUtils.isEmpty(code) || companyuserId == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        SysCompanyUser sysCompanyUser = sysCompanyUserMapper.selectById(companyuserId);
        String mobile = sysCompanyUser.getMobile();
        String redisCode = redisTemplate.opsForValue().get(SMSConstant.SMS_CHANGE_MANAGER_KEY_PREFIX + mobile);
        if (StringUtils.isEmpty(redisCode) || !redisCode.equals(code)) {
            throw new NcException(ResponseEnum.INVALID_VERIFY_CODE);
        }


        SysCompanyUserDTO currentAdmin = this.getCurrentAdmin();
        LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRole::getCompanyId, currentAdmin.getCompanyId());
        wrapper.eq(SysRole::getRoleName, NcConstant.ADMIN_ROLE_SYS);
        SysRole sysRole = sysRoleMapper.selectOne(wrapper);
        SysCompanyUserRole sysCompanyUserRole = new SysCompanyUserRole();
        sysCompanyUserRole.setCompanyUserId(companyuserId);

        LambdaQueryWrapper<SysCompanyUserRole> finalWrapper = new LambdaQueryWrapper<>();
        finalWrapper.eq(SysCompanyUserRole::getCompanyUserId, currentAdmin.getId());
        finalWrapper.eq(SysCompanyUserRole::getRoleId, sysRole.getId());
        sysCompanyUserRoleMapper.update(sysCompanyUserRole, finalWrapper);

    }

}
